x86: add strictly sanity check for XSAVE/XRSTOR
authorWei Gang <gang.wei@intel.com>
Mon, 21 Feb 2011 09:11:57 +0000 (09:11 +0000)
committerWei Gang <gang.wei@intel.com>
Mon, 21 Feb 2011 09:11:57 +0000 (09:11 +0000)
Replace most checks on cpu_has_xsave with checks on new fn
xsave_enabled(), do additional sanity checks in the new fn.

Signed-off-by: Wei Gang <gang.wei@intel.com>
Signed-off-by: Keir Fraser <keir.xen@gmail.com>
xen/arch/x86/domain.c
xen/arch/x86/domctl.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/vmx/vmcs.c
xen/arch/x86/i387.c
xen/arch/x86/traps.c
xen/include/asm-x86/domain.h
xen/include/asm-x86/hvm/hvm.h
xen/include/asm-x86/i387.h

index b971df19b96a81d734fe8bae21e7a18959ba8f1d..d432eb89906f8679d402ea06d34e616c12fd86d9 100644 (file)
@@ -628,7 +628,7 @@ unsigned long pv_guest_cr4_fixup(const struct vcpu *v, unsigned long guest_cr4)
         hv_cr4_mask &= ~X86_CR4_DE;
     if ( cpu_has_fsgsbase && !is_pv_32bit_domain(v->domain) )
         hv_cr4_mask &= ~X86_CR4_FSGSBASE;
-    if ( cpu_has_xsave )
+    if ( xsave_enabled(v) )
         hv_cr4_mask &= ~X86_CR4_OSXSAVE;
 
     if ( (guest_cr4 & hv_cr4_mask) != (hv_cr4 & hv_cr4_mask) )
@@ -1402,7 +1402,7 @@ static void __context_switch(void)
         memcpy(stack_regs,
                &n->arch.guest_context.user_regs,
                CTXT_SWITCH_STACK_BYTES);
-        if ( cpu_has_xsave && n->arch.xcr0 != get_xcr0() )
+        if ( xsave_enabled(n) && n->arch.xcr0 != get_xcr0() )
             set_xcr0(n->arch.xcr0);
         n->arch.ctxt_switch_to(n);
     }
index 6fb5504d783864a09a3c213532fbbdecea07fb16..3f91f7ac2e4d2c3932a68511268ad93126dcf965 100644 (file)
@@ -1603,7 +1603,7 @@ void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c)
 #endif
 
     /* Fill legacy context from xsave area first */
-    if ( cpu_has_xsave )
+    if ( xsave_enabled(v) )
         memcpy(v->arch.xsave_area, &v->arch.guest_context.fpu_ctxt,
                sizeof(v->arch.guest_context.fpu_ctxt));
 
index ec71dfcef32354ef8299e1334ee0aa64882f7657..11f9392d608963360c93eeea3f711a5cbcd20e51 100644 (file)
@@ -676,7 +676,7 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
         return -EINVAL;
     }
 
-    if ( ctxt.cr4 & HVM_CR4_GUEST_RESERVED_BITS )
+    if ( ctxt.cr4 & HVM_CR4_GUEST_RESERVED_BITS(v) )
     {
         gdprintk(XENLOG_ERR, "HVM restore: bad CR4 0x%"PRIx64"\n",
                  ctxt.cr4);
@@ -773,7 +773,7 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h)
     memcpy(&vc->fpu_ctxt, ctxt.fpu_regs, sizeof(ctxt.fpu_regs));
 
     /* In case xsave-absent save file is restored on a xsave-capable host */
-    if ( cpu_has_xsave )
+    if ( xsave_enabled(v) )
     {
         struct xsave_struct *xsave_area = v->arch.xsave_area;
 
@@ -836,6 +836,8 @@ static int hvm_save_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
 
     for_each_vcpu ( d, v )
     {
+        if ( !xsave_enabled(v) )
+            continue;
         if ( _hvm_init_entry(h, CPU_XSAVE_CODE, v->vcpu_id, HVM_CPU_XSAVE_SIZE) )
             return 1;
         ctxt = (struct hvm_hw_cpu_xsave *)&h->data[h->cur];
@@ -861,11 +863,6 @@ static int hvm_load_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
     struct hvm_save_descriptor *desc;
     uint64_t _xfeature_mask;
 
-    /* fails since we can't restore an img saved on xsave-capable host */
-//XXX: 
-    if ( !cpu_has_xsave )
-        return -EINVAL;
-
     /* Which vcpu is this? */
     vcpuid = hvm_load_instance(h);
     if ( vcpuid >= d->max_vcpus || (v = d->vcpu[vcpuid]) == NULL )
@@ -874,6 +871,10 @@ static int hvm_load_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
         return -EINVAL;
     }
 
+    /* Fails since we can't restore an img saved on xsave-capable host. */
+    if ( !xsave_enabled(v) )
+        return -EINVAL;
+
     /* Customized checking for entry since our entry is of variable length */
     desc = (struct hvm_save_descriptor *)&h->data[h->cur];
     if ( sizeof (*desc) > h->size - h->cur)
@@ -1453,7 +1454,7 @@ int hvm_set_cr4(unsigned long value)
     struct vcpu *v = current;
     unsigned long old_cr;
 
-    if ( value & HVM_CR4_GUEST_RESERVED_BITS )
+    if ( value & HVM_CR4_GUEST_RESERVED_BITS(v) )
     {
         HVM_DBG_LOG(DBG_LEVEL_1,
                     "Guest attempts to set reserved bit in CR4: %lx",
@@ -2208,7 +2209,7 @@ void hvm_cpuid(unsigned int input, unsigned int *eax, unsigned int *ebx,
             __clear_bit(X86_FEATURE_APIC & 31, edx);
 
         /* Fix up OSXSAVE. */
-        if ( cpu_has_xsave )
+        if ( xsave_enabled(v) )
             *ecx |= (v->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSXSAVE) ?
                      bitmaskof(X86_FEATURE_OSXSAVE) : 0;
         break;
index 6f7fc1a8cc8a5b9d0815f696a4032270357fe367..18e7055157021eb3962c2220c867df804d618005 100644 (file)
@@ -760,7 +760,8 @@ static int construct_vmcs(struct vcpu *v)
     /* Host control registers. */
     v->arch.hvm_vmx.host_cr0 = read_cr0() | X86_CR0_TS;
     __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0);
-    __vmwrite(HOST_CR4, mmu_cr4_features | (cpu_has_xsave ? X86_CR4_OSXSAVE : 0));
+    __vmwrite(HOST_CR4,
+              mmu_cr4_features | (xsave_enabled(v) ? X86_CR4_OSXSAVE : 0));
 
     /* Host CS:RIP. */
     __vmwrite(HOST_CS_SELECTOR, __HYPERVISOR_CS);
index 5c96da0456776f95293f11675ac705032440e76c..7d0a9fa3f5e4ca4978e40f19be4ee0fc8731c5f3 100644 (file)
@@ -69,7 +69,7 @@ void setup_fpu(struct vcpu *v)
     if ( v->fpu_dirtied )
         return;
 
-    if ( cpu_has_xsave )
+    if ( xsave_enabled(v) )
     {
         /*
          * XCR0 normally represents what guest OS set. In case of Xen itself, 
@@ -116,7 +116,7 @@ void save_init_fpu(struct vcpu *v)
     if ( cr0 & X86_CR0_TS )
         clts();
 
-    if ( cpu_has_xsave )
+    if ( xsave_enabled(v) )
     {
         /* XCR0 normally represents what guest OS set. In case of Xen itself,
          * we set all accumulated feature mask before doing save/restore.
@@ -316,6 +316,17 @@ void xsave_free_save_area(struct vcpu *v)
     v->arch.xsave_area = NULL;
 }
 
+bool_t xsave_enabled(const struct vcpu *v)
+{
+    if ( cpu_has_xsave )
+    {
+        ASSERT(xsave_cntxt_size >= XSAVE_AREA_MIN_SIZE);
+        ASSERT(v->arch.xsave_area);
+    }
+
+    return cpu_has_xsave;      
+}
+
 /*
  * Local variables:
  * mode: C
index 81141fd4f11c2b7c5eff0718ac369d8ffa7165a7..2908b61ca35b4737ede49a91dea964c006c33ae6 100644 (file)
@@ -771,7 +771,7 @@ static void pv_cpuid(struct cpu_user_regs *regs)
         __clear_bit(X86_FEATURE_XTPR % 32, &c);
         __clear_bit(X86_FEATURE_PDCM % 32, &c);
         __clear_bit(X86_FEATURE_DCA % 32, &c);
-        if ( !cpu_has_xsave )
+        if ( !xsave_enabled(current) )
         {
             __clear_bit(X86_FEATURE_XSAVE % 32, &c);
             __clear_bit(X86_FEATURE_AVX % 32, &c);
index eaba32d1be37c1145745b5886c099133991f4e5d..8056559308c9e40665c575d5a63aa48e590bd22c 100644 (file)
@@ -464,7 +464,7 @@ unsigned long pv_guest_cr4_fixup(const struct vcpu *, unsigned long guest_cr4);
     (((v)->arch.guest_context.ctrlreg[4]                    \
       | (mmu_cr4_features & (X86_CR4_PGE | X86_CR4_PSE))    \
       | ((v)->domain->arch.vtsc ? X86_CR4_TSD : 0)         \
-      | ((cpu_has_xsave)? X86_CR4_OSXSAVE : 0))              \
+      | ((xsave_enabled(v))? X86_CR4_OSXSAVE : 0))              \
       & ~X86_CR4_DE)
 #define real_cr4_to_pv_guest_cr4(c) \
     ((c) & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_TSD | X86_CR4_OSXSAVE))
index ca122c1ab6bc67c98ca6235f8e2d04e9e2ee6508..46baf2c8942153cc09f8bb3ad3f3eef2608b680b 100644 (file)
@@ -285,13 +285,13 @@ static inline int hvm_do_pmu_interrupt(struct cpu_user_regs *regs)
     (X86_CR4_VMXE | X86_CR4_PAE | X86_CR4_MCE))
 
 /* These bits in CR4 cannot be set by the guest. */
-#define HVM_CR4_GUEST_RESERVED_BITS                     \
+#define HVM_CR4_GUEST_RESERVED_BITS(_v)                 \
     (~((unsigned long)                                  \
        (X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD |       \
         X86_CR4_DE  | X86_CR4_PSE | X86_CR4_PAE |       \
         X86_CR4_MCE | X86_CR4_PGE | X86_CR4_PCE |       \
         X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT |           \
-        (cpu_has_xsave ? X86_CR4_OSXSAVE : 0))))
+        (xsave_enabled(_v) ? X86_CR4_OSXSAVE : 0))))
 
 /* These exceptions must always be intercepted. */
 #define HVM_TRAP_MASK ((1U << TRAP_machine_check) | (1U << TRAP_invalid_op))
index 2cbbbc40e94f0e1938f24d7784e39d0869a917a0..8e10d927e120d96121093f2a846e5f73cb8cd792 100644 (file)
 #ifndef __ASM_I386_I387_H
 #define __ASM_I386_I387_H
 
-#include <xen/sched.h>
-#include <asm/processor.h>
+#include <xen/types.h>
+#include <xen/percpu.h>
+
+struct vcpu;
 
 extern unsigned int xsave_cntxt_size;
 extern u64 xfeature_mask;
@@ -20,6 +22,7 @@ extern u64 xfeature_mask;
 void xsave_init(void);
 int xsave_alloc_save_area(struct vcpu *v);
 void xsave_free_save_area(struct vcpu *v);
+bool_t xsave_enabled(const struct vcpu *v);
 
 #define XSAVE_AREA_MIN_SIZE (512 + 64) /* FP/SSE + XSAVE.HEADER */
 #define XSTATE_FP       (1ULL << 0)